package log

import (
	"context"
	"gfrest/common/ctxkit"
	"gfrest/common/log/context_log"
	"io"
	"os"
	"strconv"

	"github.com/getsentry/sentry-go"
	"github.com/gogf/gf/debug/gdebug"
	"github.com/gogf/gf/frame/g"
	"github.com/gogf/gf/net/ghttp"
	"github.com/gogf/gf/os/glog"
)

type key int

const (
	ctxLoggerKey key = iota
	// ...
)

func getContextMsg(ctx context.Context) string {

	return "ReqId: " + ctxkit.GetReqID(ctx) +
		", UserName: " + ctxkit.GetUserName(ctx) +
		", UserId: " + strconv.Itoa(int(int(ctxkit.GetUserID(ctx)))) +
		", UserIp: " + ctxkit.GetUserIP(ctx) + ", "
}

var w io.Writer

func init() {
	newFileWriter() // newFileWriter at init
}

func newFileWriter(logfile ...string) {
	var err error
	if len(logfile) > 0 {
		w, err = context_log.NewFileWriter(logfile[0], 1024*1024*50, 30)

	} else {
		os.Mkdir("log", 0700)
		w, err = context_log.NewFileWriter("log/log.log", 1024*1024*50, 30)
	}
	if err != nil {
		g.Log().Fatal(err)
	}

}

// NewCtxLogger NewCtxLogger
func NewCtxLogger(ctx context.Context, logfile ...string) *context_log.Context {
	return context_log.NewContext(ctx, w, "test", glog.LEVEL_ALL)
}

// WithCtxLogger 注入 CtxLogger
func WithCtxLogger(r *ghttp.Request) *ghttp.Request {
	r.SetCtxVar(ctxLoggerKey, NewCtxLogger(r.Context()))
	return r
}

// ContextWithCtxLogger 注入 CtxLogger
func ContextWithCtxLogger(ctx context.Context) context.Context {
	return context.WithValue(ctx, ctxLoggerKey, NewCtxLogger(ctx))
}

func getCtxLogger(ctx context.Context) *context_log.Context {
	val, ok := ctx.Value(ctxLoggerKey).(*context_log.Context)
	if !ok {
		return NewCtxLogger(ctx)
	}
	return val
}

// Printf Printf
func Printf(ctx context.Context, format string, v ...interface{}) {
	getCtxLogger(ctx).Printf(getContextMsg(ctx)+format, v...)

}

// Infof Infof
func Infof(ctx context.Context, format string, v ...interface{}) {
	getCtxLogger(ctx).Infof(getContextMsg(ctx)+format, v...)

}

// Info Info
func Info(ctx context.Context, msg interface{}) {
	// getCtxLogger(ctx).Infof(getContextMsg(ctx))
	getCtxLogger(ctx).Info(msg)

}

// Debugf Debugf
func Debugf(ctx context.Context, format string, v ...interface{}) {
	getCtxLogger(ctx).Debugf(getContextMsg(ctx)+format, v...)

}

// Debug Debug
func Debug(ctx context.Context, msg interface{}) {
	getCtxLogger(ctx).Debug(msg)
}

// Warningf Warningf
func Warningf(ctx context.Context, format string, v ...interface{}) {
	getCtxLogger(ctx).Warningf(getContextMsg(ctx)+format, v...)

}

// Errorf Errorf
func Errorf(ctx context.Context, format string, v ...interface{}) {
	getCtxLogger(ctx).Errorf(getContextMsg(ctx)+format, v...)

}

// Error Error
func Error(ctx context.Context, err interface{}) {
	errMsg := ""
	if e, ok := err.(error); ok {
		sentry.CaptureException(e)
		errMsg = e.Error()
	}
	getCtxLogger(ctx).Errorf(getContextMsg(ctx) + errMsg)
	getCtxLogger(ctx).Errorf(gdebug.StackWithFilter("ghttp"))

}

// WriteLog WriteLog
func WriteLog(ctx context.Context) {
	getCtxLogger(ctx).WriteLog()

}
